package ca.seia.comp6521.a2.itemsetstorage;

import gnu.trove.iterator.TObjectIntIterator;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import ca.seia.comp6521.a2.io.DataFileWriter;

public class IntItemCountStorage implements CountStorage<IntItems> {

private TObjectIntMap<IntItems> countMap;
	
	public IntItemCountStorage() {
		this.countMap = new TObjectIntHashMap<IntItems>();
	}
	
	public void addCount(IntItems items) {
		this.countMap.adjustOrPutValue(items, 1, 1);
	}
	
	public int getCount(IntItems items) {
		return this.countMap.get(items);
	}
	
	public void delete(IntItems items) {
		this.countMap.remove(items);
	}
	
	public int getNumberOfItemsInStorage() {
		return this.countMap.size(); 
	}
	
	public void removeInfrequentItems(int support) {
		for (Object pair :this.countMap.keys() ) {
			if(this.countMap.get(pair) < support) {
				this.countMap.remove(pair);
			}
		}
	}
	
	public void removeInfrequentPairsAndWriteToDisk(int support, DataFileWriter fileWriter) throws IOException {
		for (TObjectIntIterator iterator = countMap.iterator(); iterator.hasNext();) {
			iterator.advance();
			if ( iterator.value() >=  support) {
				//System.out.println(iterator.key());
				fileWriter.writeItems((ExternilizableItems) iterator.key(), iterator.value());
			} else {
				iterator.remove();
			}
		}
	}
	
	public List<IntItems> generateCandidateFrequentItemsForNextPass(int nextPassNumber) {
		IntItems[] keys = (IntItems[]) this.countMap.keys(new IntItems[0]);
		
		Arrays.sort(keys);
		List<IntItems> frequentCandidates = new ArrayList<IntItems>();
		
		int keyLength = keys.length;
		for(int keyIndex = 0 ; keyIndex < keyLength ; keyIndex++) {
			for(int secondPairIndex = keyIndex + 1; secondPairIndex < keyLength ; secondPairIndex++) {
				IntItems frequentCandidateItems = IntItems.generateCandidateItems(keys[keyIndex], keys[secondPairIndex],nextPassNumber);
				//System.out.println("First item = " + keys[keyIndex]);
				//System.out.println("Second item = " + keys[secondPairIndex]);
				//System.out.println(frequentCandidateItems);
				if(frequentCandidateItems == null) {
					break;
				} else {
					frequentCandidates.add(frequentCandidateItems);
				}
			}
		}
		return frequentCandidates;
	}
	
	public Set<IntItems> generateUniqueCandidateFrequentItemsForNextPass(int nextPassNumber) {
		IntItems[] keys = (IntItems[]) this.countMap.keys(new IntItems[0]);
		
		Arrays.sort(keys);
		Set<IntItems> frequentCandidates = new HashSet<IntItems>();
		
		int keyLength = keys.length;
		for(int keyIndex = 0 ; keyIndex < keyLength ; keyIndex++) {
			for(int secondPairIndex = keyIndex + 1; secondPairIndex < keyLength ; secondPairIndex++) {
				IntItems frequentCandidateItems = IntItems.generateCandidateItems(keys[keyIndex], keys[secondPairIndex],nextPassNumber);
				//System.out.println("First item = " + keys[keyIndex]);
				//System.out.println("Second item = " + keys[secondPairIndex]);
				//System.out.println(frequentCandidateItems);
				if(frequentCandidateItems == null) {
					break;
				} else {
					frequentCandidates.add(frequentCandidateItems);
				}
			}
		}
		return frequentCandidates;
	}
	
	

	@Override
	public String toString() {
		return "IntItemCountStorage [countMap=" + countMap + "]" + "size of map " + this.countMap.size() ;
	}
}
